تحميل النواة من القرص المرن

 

 

هذا الدرس أردته استمرارا للدرس الذي وضعه الأخ   IDOIT و الذي يوضح كيفية كتابة قطاع الانطلاق. و الهدف منه هو المرور إلى المرحلة الطبيعية الموالية و هي تحميل النواة من القرص المرن.

 

 

المطلوب قراءة الدرس الأول المشار إليه أعلاه حتى تتمكن من فهم ما سوف يأتي.

 

إذا تتبعت الدر س السابق فقد وصلت إلى مرحلة نسخ جملة على الشاشة النصية بعد تحميل قطاع الانطلاق، وهذا هو البرنامج

 

[BITS 16]

 

EntryPoint:

        mov  ax,07c0h

        mov  ds,ax

        mov  es,ax

 

        mov  ax,09000h

        mov  ss,ax

        mov  sp,0ffffh

 

        mov si,Salam

        call ShowMsg

 

k_loop:

        jmp k_loop

 

ShowMsg:

        push  ax

        push  bx

.loop_start:

        lodsb

        cmp  al,0

        je      .loop_end

        mov  ah,0Eh

        mov  bx,07h

        int     10h

        jmp   .loop_start

.loop_end:

        pop   bx

        pop   ax

        ret

 

 

 

Salam        db     "Salam Alikom !",13,10,0

 

times 510-($-$$) db 0

 

DW 0AA55h 

 

 

 

 

 

الآن سوف نقوم بما يلي

 

1-   استعمال الانقطاع 0x13 من أجل تحميل النواة .

2-   كتابة برنامج النواة : في هذه المرحلة سوف نكتفي بعرض جملة أخرى على الشاشة، وفي مراحل قادمة إن شاء الله سنقوم بأشياء أكثر جدية

 

أولا - شرح  موجز لبنية وطريقة عمل الأقراص :

 

داخل الغلاف البلاستيكي يوجد قرص مغلف بشريط مغناطيسي ( مثل أشرطة الفيديو)، عندما يراد تخزين المعلومات داخل القرص يقوم قارئ الأقراص بتشفير المعلومات على شكل رموز مغناطيسية. بالطريقة نفسها يقوم القارئ عند القراءة بفك هذه الرموز و ترجمتها إلى رموز ثنائية (Binary).

 

الشكل 1-1:  الأقراص في القرص الصلب متراصة على شكل حزمة (stack)

 

يحتوي القارئ على: - محرك يقوم بجعل القرص يدور بسرعة معينة.   – رأسين من أجل القراءة و الكتابة، كل رأس في جهة ( هذا لأن القرص المرن يحتوي على جهتين). – كل من الرأسين متصل بذراع آلي يقوم بتحريك الرأس من وسط القرص إلى جانبه أو العكس عبر شعاع الحلقات.

تتقسم مساحة القرص إلى حلقات دائرية بدءا بحواف القرص و انتهاء بوسطه ( أنظر الشكل 1-1)، كل حلقة مقسمة إلى عدة قطاعات. و كل قطاع يحتوي على نفس الكمية من المعلومات، في أغلب الأحيان يكون طول القطاع 512 بايت.

الأقراص الصلبة لها نفس التصميم، الفرق الوحيد هو أنه بدل قرص بلاستيكي يوجد قرص من مادة صلبة كالزجاج مما يتيح لها الدوران بسرعة أكبر بكثير من الأقراص المرنة. ذلك ما يجعل القراءة والكتابة في الأقراص الصلبة أسرع بكثير. أيضا بدل الوجه المزدوج للقرص المرن  توجد به عدة أقراص مرتبة فوق بعضها البعض.

 

الشكل 2-1:  الأقراص في القرص الصلب متراصة على شكل كومة (stack)

 

بما أن للقرص المرن وجهان (و للقرص الصلب عدة أوجه)، تشكل الحلقات التي توجد في نفس الترتيب على مختلف الأوجه ما يشبه الموشور(cylinder).

 

الشكل 3-1:   الحلقات الموجودة على نفس الترتيب تشكل موشورا

 

 

من وجهة نظر المبرمج، من أجل قراءة أو كتابة قطاع معين ينبغي تحديد : 1- رقم الموشور، 2- رقم الجهة ( أو الرأس) داخل الموشور، 3- رقم القطاع داخل الحلقة.

يتم تخزين البيانات وفقا للترتيب التالي، أولا القطاع الأول على الجهة الأولى في الموشور الموجود على أقصى الحافة، ثم القطاع الثاني إلى أن تستنفذ كل قطاعات الجهة، ثم يتم المرور إلى الجهة الثانية في نفس الموشور و هكذا دواليك، بعد ذلك يتم المرور إلى الموشور الثاني فالثالث إلى غاية آخر موشور في الوسط.

 

يجب التنبيه هنا على أن أرقام القطاعات تبدأ من 1 بينما أرقام الموشورات والجهات تبدأ من الصفر.

 

من أجل قراءة القطاعات بالبيوس نستعمل الوظيفة رقم 2 في الإنقطاع 0x13. فيما يلي شرح لكيفية استعمال هذه الوظيفة لقراءة القرص المرن

 

استعمال الوظيفة 2: تقوم بقراءة القطاعات من القرص المرن أو الصلب

 

المدخل(input)

 

es:bx -  الموقع الذي سيحمل إليه القطاع (أو القطاعات) في الذاكرة

es: عنوان القسم (segment adress)

bx: العنوان داخل القسم (Offset)

 

ah        -  رقم الوظيفة (2)

dh       – رقم الوجه ( القرص المرن له وجهان الوجه الأول يبدأ ب 0)

dl         -  رقم القارئ ( 0: القرص المرن A )

ch        – رقم الموشور

cl         – رقم القطاع (القطاعات تبدأ من 1)

al         – عدد القطاعات المطلوب قراءتها

 

المخرج  (output)

 

CF (carry flag) = 0:  نجحت العملية، و تم تحميل البيانات إلى العنوان المطلوب

CF (carry flag) = 1: هناك خطأ، السجل ah يحتوي على رمز الخطأ

 

 

 

 

في هذه المرحلة سيكن لدينا برنامجان، الأول هو قطاع الانطلاق و طوله 512 بايت يتم تخزينه على القطاع الأول، يأتي بعده برنامج النواة على القطاع الثاني.

 

بعد هذه المقدمة يمكننا المرور إلى كتابة البرنامج.  فيما يلي الإضافات التي سندخلها على قطاع الانطلاق

 

 

mov [bootdrv], dl

dl يحتوي على رقم القرص الذي تم الانطلاق منه، نقوم بتحزينه في المتغير bootdrv

xor ax, ax

int 0x13

 

استعمال الوظيفة 0 :  الهدف هو تهيئة القرص من أجل القراءة

الإنقطاع 0x13  هو المدخل إلى الوظائف المتعلقة بالأقراص

 

mov ax,0x100

mov es,ax

mov bx,0

mov ah,2

mov al,1

mov ch,0

mov cl,2

mov dh,0

mov dl,[bootdrv]

int 0x13

jc readFail

ret

 

readFail:

mov si, readErrorMsg

call ShowMsg

ret

استعمال الوظيفة  2: تقوم بقراءة القطاعات من القرص المرن أو الصلب

 

es:bx -  الموقع الذي سيحمل إليه القطاع (أو القطاعات) في الذاكرة في هذه الحالة : 0x100:0 (=  0x1000)

ah        -  رقم الوظيفة (2)

dh       – رقم الوجه ( القرص المرن له وجهان الوجه الأول يبتدء ب 0)

dl         -  رقم القارئ ( 0: القرص المرن A )

ch        – رقم الموشور

cl         – رقم القطاع

al         – عدد القطاعات المطلوب قراءتها

 

في حالة وقوع خطأ(CF=1-> jc = true)  نقفز إلى readFail حيث  نقوم بكتابة الجملة

  "Error, unable to read from floppy"

 

 

بعد هذه التعليمات نكون قد حملنا النواة إلى العنوان 0x100:0 (أي العنوان 0x1000[=0x100*4+0] بالصيغة الخطية). للبدء بتنفيذ النواة نقوم بالقفز إلى العنوان المذكور.

 

jmp dword 0x100:0

يتم القفز إلى العنوان الذي حملت إليه النواة

 

 

فيما يلي النص الكامل، التغييرات تم إدخالها بخطوط بارزة

 

[BITS 16]

 

EntryPoint:

          mov [bootdrv], dl

mov    ax,07c0h

          mov    ds,ax

          mov    es,ax

 

          mov    ax,09000h

          mov    ss,ax

          mov    sp,0ffffh

 

          mov si,Salam

          call ShowMsg

 

xor ax, ax

int 0x13

 

mov ax, 0x100

mov es,ax

mov bx,0

mov ah,2

mov al,1

mov ch,0

mov cl,2

mov dh,0

mov dl, [bootdrv]

int 0x13

jc readFail

 

jmp dword 0x100:0

 

readFail:

mov si, readError

call ShowMsg

 

k_loop:

          jmp k_loop

 

ShowMsg:

          push   ax

          push   bx

.loop_start:

          lodsb

          cmp    al,0

          je        .loop_end

          mov    ah,0Eh

          mov    bx,07h

          int       10h

          jmp     .loop_start

.loop_end:

          pop     bx

          pop     ax

          ret

 

 

bootdrv db 0

 

Salam            db     "Salam Alikom !",13,10,0

readError db     "Error, unable to read from floppy",13,10,0

 

times 510-($-$$) db 0

 

DW 0AA55h

 

 

 

2- كتابة برنامج النواة

 

 

هذا البرنامج بسيط و يقوم فقط بكتابة جملة kernel is loaded على الشاشة.

 

أنقل هذه التعليمات في ملف kernel.s ثم احفظ الملف في نفس المجلد الذي يحتضن ملف قطاع الانطلاق.

 

[BITS 16]

ORG 0

 

التعليمات مشفرة على 16 بايت

يتم إخبار Nasm بأن السجل cs يحتوي على العنوان 0

 

 

mov ax,0x100

mov ds,ax

mov es,ax

mov ax,0x9000

mov ss,ax

mov sp, 0xffff

 

mov si,krnlMsg

call ShowMsg

 

 

krnlMasg db "Kernel loaded",13,10,0

1-  نقوم بملئ المسجلات ds & es بالعنوان الذي يتم التحميل إليه

2-  لكتابة الجملة على الشاشة نستعين بنفس الكود الذي استعمل في كتابة قطاع الانطلاق.  يمكن نسخ الكود و إلصاقه تحت call ShowMsg

 

 

 

 

ملحوظة: بما أننا نستعمل ShowMsg  أكثر من مرة يمكننا وضعها في ملف مستقل و من ثم إدخالها في الملفين السابقين عبر الأمر %include

 

 

للترجمة نستعمل نفس التعليمة

 

Nasm –f bin boot.s o boot.bin

Nasm –f bin kernel.s kernel.bin

 

لنقل الملفات إلى القرص المرن

 

cat  boot.bin kernel.bin | dd of=/dev/fd0 bs=512

 

بالنسبة لمستعملي ويندوز

 

copy /b boot.bin+kernel.bin  boot.img

 

لنقل الملف boot  إلى القرص المرن يمكنك الاستعانة بالبرنامج ntrawrite المرفق مع الدرس

 

ntrawrite –f boot.img

 

عند السؤال please type the diskette drive عليك الإجابة ب A

 

إذا أردت كتابة الملف على صورة للقرص من أجل استعمالها مع برنامج لمحاكاة الحاسب مثل Boschs

 

cat  boot.bin kernel.bin | dd of=image_file bs=512 conv=notrunc

 

مع استبدالimage_file   باسم الملف الفعلي.

 

 

 

 

3- النتيجة:

 

إذا تتبعت التعليمات أعلاه، لديك الآن برنامج لقطاع الانطلاق يستطيع تحميل النواة من القرص المرن. ولديك أيضا نواة، صحيح لا تقوم بالشيئ الكثير لكنها البداية فقط و يمكننا تطويره فيما بعد.

 

في الدرس القادم إن شاء الله سنقوم بدراسة أوضاع المعالج x86 وتوضيح كيفية المرور إلى الوضع المحمي الذي تعمل عليه كل أنظمة التشغيل الحديثة.